<!DOCTYPE html>
<html lang="zh">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
	<meta name="keywords" content="dromara.org" />
	<meta name="description" content="dromara.org" />
	<!-- 网页标签标题 -->
	<title>dromara(Open source organization)</title>
	<link rel="shortcut icon" href="/website/img/docsite.ico"/>
	<link rel="stylesheet" href="/website/build/documentation.css" />
</head>
<body>
	<div id="root"><div class="documentation-page" data-reactroot=""><header class="header-container header-container-normal"><div class="header-body"><a href="/website/zh-cn/index.html"><img class="logo" src="/website/img/dromara.png"/></a><div class="search search-normal"><span class="icon-search"></span></div><div class="header-menu"><img class="header-menu-toggle" src="/website/img/system/menu_gray.png"/><ul><li class="menu-item menu-item-normal"><a href="/website/zh-cn/index.html" target="_self">首页</a></li><li class="menu-item menu-item-normal menu-item-normal-active"><a href="/website/zh-cn/docs/soul/soul.html" target="_self">文档</a></li><li class="menu-item menu-item-normal"><a href="/website/zh-cn/blog/index.html" target="_self">博客</a></li><li class="menu-item menu-item-normal"><a href="/website/zh-cn/community/index.html" target="_self">社区</a></li></ul></div></div></header><div class="bar"><div class="bar-body"><img src="/website/img/system/docs.png" class="front-img"/><span>文档</span><img src="/website/img/system/docs.png" class="back-img"/></div></div><section class="content-section"><div class="sidemenu"><div class="sidemenu-toggle"><img src="https://img.alicdn.com/tfs/TB1E6apXHGYBuNjy0FoXXciBFXa-200-200.png"/></div><ul><li class="menu-item menu-item-level-1"><span>Soul</span><ul><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/soul/soul.html" target="_self">soul介绍</a></li><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/soul/db.html" target="_self">数据库设计</a></li><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/soul/config.html" target="_self">配置中心设计</a></li><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/soul/request.html" target="_self">请求参数设计</a></li><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/soul/selector.html" target="_self">选择器规则设计</a></li><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/soul/preFilter.html" target="_self">前置过滤器设计</a></li><li style="height:324px;overflow:hidden" class="menu-item menu-item-level-2"><span>插件介绍<img style="transform:rotate(0deg)" class="menu-toggle" src="/website/img/system/arrow_down.png"/></span><ul><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/soul/divide.html" target="_self">divide插件</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/soul/dubbo.html" target="_self">dubbo插件</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/soul/springcloud.html" target="_self">springcloud插件</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/soul/rateLimiter.html" target="_self">rateLimiter插件</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/soul/monitor.html" target="_self">monitor插件</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/soul/waf.html" target="_self">waf插件</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/soul/sign.html" target="_self">sign插件</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/soul/rewrite.html" target="_self">rewrite插件</a></li></ul></li><li style="height:108px;overflow:hidden" class="menu-item menu-item-level-2"><span>部署文档<img style="transform:rotate(0deg)" class="menu-toggle" src="/website/img/system/arrow_down.png"/></span><ul><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/soul/admin.html" target="_self">部署admin</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/soul/server.html" target="_self">部署server</a></li></ul></li><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/soul/http.html" target="_self">使用手册</a></li><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/soul/extend.html" target="_self">扩展文档</a></li></ul></li><li class="menu-item menu-item-level-1"><span>Hmily</span><ul><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/hmily/index.html" target="_self">介绍文档</a></li><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/hmily/configuration.html" target="_self">配置详解</a></li><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/hmily/admin.html" target="_self">启动admin</a></li><li style="height:144px;overflow:hidden" class="menu-item menu-item-level-2"><span>用户文档<img style="transform:rotate(0deg)" class="menu-toggle" src="/website/img/system/arrow_down.png"/></span><ul><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/hmily/user-dubbo.html" target="_self">dubbo用户</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/hmily/user-motan.html" target="_self">motan用户</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/hmily/user-springcloud.html" target="_self">springcloud用户</a></li></ul></li><li style="height:108px;overflow:hidden" class="menu-item menu-item-level-2"><span>快速体验<img style="transform:rotate(0deg)" class="menu-toggle" src="/website/img/system/arrow_down.png"/></span><ul><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/hmily/quick-start-dubbo.html" target="_self">quick-start-dubbo</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/hmily/quick-start-springcloud.html" target="_self">quick-start-springcloud</a></li></ul></li></ul></li><li class="menu-item menu-item-level-1"><span>raincat</span><ul><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/raincat/index.html" target="_self">介绍文档</a></li><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/raincat/start-manager.html" target="_self">启动raincat-manager</a></li><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/raincat/config.html" target="_self">配置详解</a></li><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/raincat/admin.html" target="_self">启动admin</a></li><li style="height:144px;overflow:hidden" class="menu-item menu-item-level-2"><span>用户文档<img style="transform:rotate(0deg)" class="menu-toggle" src="/website/img/system/arrow_down.png"/></span><ul><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/raincat/user-dubbo.html" target="_self">dubbo用户</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/raincat/user-motan.html" target="_self">motan用户</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/raincat/user-springcloud.html" target="_self">springcloud用户</a></li></ul></li><li style="height:108px;overflow:hidden" class="menu-item menu-item-level-2"><span>快速体验<img style="transform:rotate(0deg)" class="menu-toggle" src="/website/img/system/arrow_down.png"/></span><ul><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/raincat/quick-start-dubbo.html" target="_self">quick-start-dubbo</a></li><li class="menu-item menu-item-level-3"><a href="/website/zh-cn/docs/raincat/quick-start-springcloud.html" target="_self">quick-start-springcloud</a></li></ul></li></ul></li><li class="menu-item menu-item-level-1"><span>myth</span><ul><li style="height:36px;overflow:hidden" class="menu-item menu-item-level-2"><a href="/website/zh-cn/docs/myth/index.html" target="_self">介绍文档</a></li></ul></li></ul></div><div class="doc-content markdown-body"><ul>
<li>
<p>soul 提供了扩展demo 项目是<a href="https://github.com/Dromara/soul/tree/master/soul-extend-demo">soul-extend-demo</a></p>
</li>
<li>
<p>soul 提供了2种方式的扩展：</p>
</li>
<li>
<p>第一种是实现 SoulPlugin接口：</p>
</li>
</ul>
<pre><code class="language-java"><span class="hljs-keyword">package</span> org.dromara.soul.web.plugin;

<span class="hljs-keyword">import</span> org.dromara.soul.common.enums.PluginTypeEnum;
<span class="hljs-keyword">import</span> org.springframework.web.server.ServerWebExchange;
<span class="hljs-keyword">import</span> reactor.core.publisher.Mono;

<span class="hljs-comment">/**
 * the soul plugin interface.
 *
 * <span class="hljs-doctag">@author</span> xiaoyu
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">SoulPlugin</span> </span>{

    <span class="hljs-comment">/**
     * Process the Web request and (optionally) delegate to the next
     * {<span class="hljs-doctag">@code</span> WebFilter} through the given {<span class="hljs-doctag">@link</span> SoulPluginChain}.
     *
     * <span class="hljs-doctag">@param</span> exchange the current server exchange
     * <span class="hljs-doctag">@param</span> chain    provides a way to delegate to the next filter
     * <span class="hljs-doctag">@return</span> {<span class="hljs-doctag">@code</span> Mono&lt;Void&gt;} to indicate when request processing is complete
     */</span>
    <span class="hljs-function">Mono&lt;Void&gt; <span class="hljs-title">execute</span><span class="hljs-params">(ServerWebExchange exchange, SoulPluginChain chain)</span></span>;

    <span class="hljs-comment">/**
     * return plugin type.
     * the plugin execution order
     * before type The first to perform then Function Type ,then last type.
     *
     * <span class="hljs-doctag">@return</span> {<span class="hljs-doctag">@linkplain</span> PluginTypeEnum}
     */</span>
    <span class="hljs-function">PluginTypeEnum <span class="hljs-title">pluginType</span><span class="hljs-params">()</span></span>;

    <span class="hljs-comment">/**
     * return plugin order .
     * This attribute To determine the plugin execution order in the same type plugin.
     *
     * <span class="hljs-doctag">@return</span> int order
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">getOrder</span><span class="hljs-params">()</span></span>;

    <span class="hljs-comment">/**
     * acquire plugin name.
     * this is plugin name define  if you extend {<span class="hljs-doctag">@linkplain</span> AbstractSoulPlugin } you must Provide the right name.
     * if you impl AbstractSoulPlugin this attribute not use.
     *
     * <span class="hljs-doctag">@return</span> plugin name.
     */</span>
    <span class="hljs-function">String <span class="hljs-title">named</span><span class="hljs-params">()</span></span>;

    <span class="hljs-comment">/**
     * plugin is execute.
     * if return true this plugin can not execute.
     *
     * <span class="hljs-doctag">@param</span> exchange the current server exchange
     * <span class="hljs-doctag">@return</span> default false.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">default</span> Boolean <span class="hljs-title">skip</span><span class="hljs-params">(ServerWebExchange exchange)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
    }

</code></pre>
<ul>
<li>plugnType():是表示该插件的执行顺序与功能，BEFORE是最开始执行，Function 是中间，Last是最后执行。方便使用与扩展。</li>
<li>getOrder():是指同一种类型插件执行时候的先后顺序。</li>
<li>named()：插件命名。</li>
<li>skip(): 该插件是否需要跳过，默认不跳过。</li>
<li>execute():插件执行的链条，会传递到下一个插件，责任链模式了解一下。</li>
</ul>
<h3>如果是实现SoulPlugin的话，只需要将你的实现类声明为Spring的bean就行。</h3>
<ul>
<li>第二种是继承AbstractSoulPlugin插件,这种就比较困难了，您需要开发后台插件来实现你自己想要功能</li>
</ul>
<pre><code class="language-java"><span class="hljs-comment">/*
 *
 *  * Licensed to the Apache Software Foundation (ASF) under one or more
 *  * contributor license agreements.  See the NOTICE file distributed with
 *  * this work for additional information regarding copyright ownership.
 *  * The ASF licenses this file to You under the Apache License, Version 2.0
 *  * (the "License"); you may not use this file except in compliance with
 *  * the License.  You may obtain a copy of the License at
 *  *
 *  *     http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  * Unless required by applicable law or agreed to in writing, software
 *  * distributed under the License is distributed on an "AS IS" BASIS,
 *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  * See the License for the specific language governing permissions and
 *  * limitations under the License.
 *
 */</span>

<span class="hljs-keyword">package</span> org.dromara.soul.web.plugin;

<span class="hljs-keyword">import</span> lombok.RequiredArgsConstructor;
<span class="hljs-keyword">import</span> org.apache.commons.collections4.CollectionUtils;
<span class="hljs-keyword">import</span> org.dromara.soul.common.constant.Constants;
<span class="hljs-keyword">import</span> org.dromara.soul.common.dto.zk.PluginZkDTO;
<span class="hljs-keyword">import</span> org.dromara.soul.common.dto.zk.RuleZkDTO;
<span class="hljs-keyword">import</span> org.dromara.soul.common.dto.zk.SelectorZkDTO;
<span class="hljs-keyword">import</span> org.dromara.soul.common.enums.PluginEnum;
<span class="hljs-keyword">import</span> org.dromara.soul.common.enums.SelectorTypeEnum;
<span class="hljs-keyword">import</span> org.dromara.soul.common.result.SoulResult;
<span class="hljs-keyword">import</span> org.dromara.soul.common.utils.JSONUtils;
<span class="hljs-keyword">import</span> org.dromara.soul.common.utils.LogUtils;
<span class="hljs-keyword">import</span> org.dromara.soul.web.cache.ZookeeperCacheManager;
<span class="hljs-keyword">import</span> org.dromara.soul.web.condition.strategy.MatchStrategyFactory;
<span class="hljs-keyword">import</span> org.dromara.soul.web.request.RequestDTO;
<span class="hljs-keyword">import</span> org.slf4j.Logger;
<span class="hljs-keyword">import</span> org.slf4j.LoggerFactory;
<span class="hljs-keyword">import</span> org.springframework.http.HttpStatus;
<span class="hljs-keyword">import</span> org.springframework.web.server.ServerWebExchange;
<span class="hljs-keyword">import</span> reactor.core.publisher.Mono;

<span class="hljs-keyword">import</span> java.util.List;
<span class="hljs-keyword">import</span> java.util.Objects;


<span class="hljs-comment">/**
 * abstract soul plugin please extends.
 *
 * <span class="hljs-doctag">@author</span> xiaoyu(Myth)
 */</span>
<span class="hljs-meta">@SuppressWarnings</span>(<span class="hljs-string">"unchecked"</span>)
<span class="hljs-meta">@RequiredArgsConstructor</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AbstractSoulPlugin</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">SoulPlugin</span> </span>{

    <span class="hljs-comment">/**
     * logger.
     */</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Logger LOGGER = LoggerFactory.getLogger(AbstractSoulPlugin.class);

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> ZookeeperCacheManager zookeeperCacheManager;

    <span class="hljs-comment">/**
     * this is Template Method child has Implement your own logic.
     *
     * <span class="hljs-doctag">@param</span> exchange exchange the current server exchange {<span class="hljs-doctag">@linkplain</span> ServerWebExchange}
     * <span class="hljs-doctag">@param</span> chain    chain the current chain  {<span class="hljs-doctag">@linkplain</span> ServerWebExchange}
     * <span class="hljs-doctag">@param</span> rule     rule    {<span class="hljs-doctag">@linkplain</span> RuleZkDTO}
     * <span class="hljs-doctag">@return</span> {<span class="hljs-doctag">@code</span> Mono&lt;Void&gt;} to indicate when request handling is complete
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">abstract</span> Mono&lt;Void&gt; <span class="hljs-title">doExecute</span><span class="hljs-params">(ServerWebExchange exchange, SoulPluginChain chain, RuleZkDTO rule)</span></span>;


    <span class="hljs-comment">/**
     * Process the Web request and (optionally) delegate to the next
     * {<span class="hljs-doctag">@code</span> WebFilter} through the given {<span class="hljs-doctag">@link</span> SoulPluginChain}.
     *
     * <span class="hljs-doctag">@param</span> exchange the current server exchange
     * <span class="hljs-doctag">@param</span> chain    provides a way to delegate to the next filter
     * <span class="hljs-doctag">@return</span> {<span class="hljs-doctag">@code</span> Mono&lt;Void&gt;} to indicate when request processing is complete
     */</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Mono&lt;Void&gt; <span class="hljs-title">execute</span><span class="hljs-params">(<span class="hljs-keyword">final</span> ServerWebExchange exchange, <span class="hljs-keyword">final</span> SoulPluginChain chain)</span> </span>{
        <span class="hljs-keyword">final</span> PluginZkDTO redisDTO = zookeeperCacheManager.findPluginByName(named());
        <span class="hljs-keyword">if</span> (!(skip(exchange) || redisDTO == <span class="hljs-keyword">null</span> || !redisDTO.getEnabled())) {
            <span class="hljs-comment">//获取selector</span>
            <span class="hljs-keyword">final</span> List&lt;SelectorZkDTO&gt; selectors = zookeeperCacheManager.findSelectorByPluginName(named());
            <span class="hljs-keyword">if</span> (CollectionUtils.isEmpty(selectors)) {
                <span class="hljs-keyword">return</span> chain.execute(exchange);
            }
            RuleZkDTO rule = selectors.stream()
                    .filter(selector -&gt; selector.getEnabled() &amp;&amp; filterSelector(selector, exchange))
                    .findFirst()
                    .map(selectorZkDTO -&gt; {
                        <span class="hljs-comment">//如果打印日志</span>
                        <span class="hljs-keyword">if</span> (selectorZkDTO.getLoged()) {
                            LogUtils.info(LOGGER, named() + <span class="hljs-string">" selector success selector name :{}"</span>, selectorZkDTO::getName);
                        }
                        <span class="hljs-keyword">final</span> List&lt;RuleZkDTO&gt; rules =
                                zookeeperCacheManager.findRuleBySelectorId(selectorZkDTO.getId());
                        <span class="hljs-keyword">if</span> (CollectionUtils.isEmpty(rules)) {
                            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
                        }
                        <span class="hljs-keyword">return</span> filterRule(exchange, rules);

                    }).orElse(<span class="hljs-keyword">null</span>);

            <span class="hljs-keyword">final</span> RequestDTO body = exchange.getAttribute(Constants.REQUESTDTO);

            <span class="hljs-keyword">if</span> (Objects.nonNull(rule)) {
                <span class="hljs-keyword">if</span> (rule.getLoged()) {
                    LogUtils.info(LOGGER, () -&gt; {
                        <span class="hljs-keyword">assert</span> body != <span class="hljs-keyword">null</span>;
                        <span class="hljs-keyword">return</span> body.getModule() + <span class="hljs-string">":"</span> + body.getMethod() + <span class="hljs-string">"  match  "</span> + named() + <span class="hljs-string">"  rule  is name :"</span> + rule.getName();
                    });
                }
                <span class="hljs-keyword">return</span> doExecute(exchange, chain, rule);
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-comment">//If the divide or dubbo or spring cloud plug-in does not match, return directly</span>
                <span class="hljs-keyword">if</span> (PluginEnum.DIVIDE.getName().equals(named())
                        || PluginEnum.DUBBO.getName().equals(named())
                        || PluginEnum.SPRING_CLOUD.getName().equals(named())) {
                    LogUtils.info(LOGGER, () -&gt; Objects.requireNonNull(body).getModule() + <span class="hljs-string">":"</span> + body.getMethod() + <span class="hljs-string">" not match  "</span> + named() + <span class="hljs-string">"  rule"</span>);
                    <span class="hljs-keyword">final</span> SoulResult error = SoulResult.error(HttpStatus.NOT_FOUND.value(), Constants.UPSTREAM_NOT_FIND);
                    <span class="hljs-keyword">return</span> exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(Objects.requireNonNull(JSONUtils.toJson(error)).getBytes())));
                }
                <span class="hljs-keyword">return</span> chain.execute(exchange);
            }
        }
        <span class="hljs-keyword">return</span> chain.execute(exchange);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> Boolean <span class="hljs-title">filterSelector</span><span class="hljs-params">(<span class="hljs-keyword">final</span> SelectorZkDTO selector, <span class="hljs-keyword">final</span> ServerWebExchange exchange)</span> </span>{
        <span class="hljs-keyword">if</span> (selector.getType() == SelectorTypeEnum.CUSTOM_FLOW.getCode()) {
            <span class="hljs-keyword">if</span> (CollectionUtils.isEmpty(selector.getConditionZkDTOList())) {
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
            }
            <span class="hljs-keyword">return</span> MatchStrategyFactory.of(selector.getMatchMode())
                    .match(selector.getConditionZkDTOList(), exchange);
        }
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> RuleZkDTO <span class="hljs-title">filterRule</span><span class="hljs-params">(<span class="hljs-keyword">final</span> ServerWebExchange exchange, <span class="hljs-keyword">final</span> List&lt;RuleZkDTO&gt; rules)</span> </span>{
        <span class="hljs-keyword">return</span> rules.stream()
                .filter(rule -&gt; Objects.nonNull(rule) &amp;&amp; rule.getEnabled())
                .filter((RuleZkDTO ruleZkDTO) -&gt; MatchStrategyFactory.of(ruleZkDTO.getMatchMode())
                        .match(ruleZkDTO.getConditionZkDTOList(), exchange))
                .findFirst().orElse(<span class="hljs-keyword">null</span>);
    }
}

</code></pre>
<ul>
<li>doExecute() 需要实现此抽象方法来实现你的特殊定制，当然，你还要开发admin管理后台，这个插件的具体规则是什么？难度比较高，需要对Soul比较熟悉。</li>
</ul>
</div></section><footer class="footer-container"><div class="footer-body"><img src="/website/img/dromara.png"/><div class="cols-container"><div class="col col-12"><h3>免责声明</h3><p>任何单位或个人转载本网站的所有相关信息，请注明来源。</p></div><div class="col col-6"><dl><dt>文档</dt><dd><a href="/website/zh-cn/docs/soul/soul.html" target="_self">概览</a></dd><dd><a href="/website/zh-cn/docs/soul/soul.html" target="_self">快速开始</a></dd><dd><a href="/website/zh-cn/docs/soul/soul.html" target="_self">开发者指南</a></dd></dl></div><div class="col col-6"><dl><dt>资源</dt><dd><a href="/website/zh-cn/blog/index.html" target="_self">博客</a></dd><dd><a href="/website/zh-cn/community/index.html" target="_self">社区</a></dd></dl></div></div><div class="copyright"><span>Copyright ©2018 549477611@qq.com by xiaoyu</span></div></div></footer></div></div>
	<script src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js"></script>
	<script src="https://f.alicdn.com/react/15.4.1/react-dom.min.js"></script>
	<script>
		window.rootPath = '/website';
  </script>
	<script src="/website/build/documentation.js"></script>
</body>
</html>